// import fs from "fs";
// import path from "path";
// import { ValueType as VT } from "k-coder";

// /** Typescript kproto 协议构建 */
// export default class TsKprotoBuilder {

//     /** 通用结构定义 */
//     private comDefs: ICommonDef[] = [];
//     /** 协议结构定义 */
//     private protoDefs: IProtoDef[] = [];
//     /** 当前协议号 */
//     private curProtocol: number = 0;
//     /** 协议号区间定义 */
//     private protocolDefs: { fileName: string, def: number[] }[] = [];
//     /** 代码 */
//     private codeStr: string = "";

//     constructor(
//         /** 协议目录 */
//         readonly inputDir: string,
//         /** 输出目录 */
//         readonly outputDir: string,
//         /** 输出类名 */
//         readonly clsName = "Proto"
//     ) {

//     }

//     /** 构建协议  */
//     build() {
//         this.loadAllProto();
//         this.sortProto();
//         this.buildCodeStr();
//         fs.writeFileSync(path.resolve(this.outputDir, `${this.clsName}.ts`), this.codeStr, { encoding: "utf-8", flag: "w+" })
//     }

//     /** 读取所有协议 */
//     private loadAllProto() {
//         //遍历协议目录及其子目录读取协议
//         (function eachDir(dir: string, fn: (filePath: string, fileName: string) => void) {
//             fs.readdirSync(dir).forEach(fileName => {
//                 let filePath = path.resolve(dir, fileName);
//                 if (fs.statSync(path.resolve(dir, fileName)).isDirectory()) {
//                     //递归遍历子目录
//                     eachDir(filePath, fn);
//                 } else {
//                     fn(filePath, fileName);
//                 }
//             })
//         })(this.inputDir, (filePath, fileName) => {
//             let match = fileName.match(/(.*)\.kproto$/);
//             if (match) {
//                 //检查命名是否规范
//                 console.log(filePath);
//                 assert(!match[1].match(/[^_0-9a-zA-Z]/), `[${fileName}.kproto]命名不规范`);
//                 let file = fs.readFileSync(filePath, "utf-8");
//                 this.loadProto(file, match[1]);
//             }
//         });
//     }

//     /** 读取单个协议 */
//     private loadProto(file: string, fileName: string) {

//         //忽略#号后内容
//         file = file.replace(/#.*/g, "");
//         let protocolDef: number[];
//         let curProtocol: number;
//         let def: IStructDef;
//         let comDef: ICommonDef;
//         let protoDef: IProtoDef;
//         let structs: IStructDef[];
//         let struct: IStructDef;
//         let note: string[] = [];


//         //遍历每行读取定义
//         file.split(/\r?\n/).forEach((ln, lnIdx) => {
//             if (!ln) return;
//             if (!protocolDef) {
//                 //找出protocol定义
//                 let match = ln.match(/^protocol *= *(.*) *;?/)
//                 if (match) {

//                     match = assert(match[1].match(/(\/)|(\d+,\d+)/), errMsg("protocol格式不正确"));
//                     if (match[1]) {
//                         protocolDef = [];
//                     } else {
//                         let span = match[2].split(",");
//                         protocolDef = [parseInt(span[0]), parseInt(span[1])];
//                         assert(protocolDef[0], errMsg("protocol定义错误：起始协议号不能为0"));
//                         assert(protocolDef[0] <= protocolDef[1], errMsg("protocol定义错误：起始协议号不能大于结束协议号"));
//                         this.protocolDefs.forEach(def => {
//                             //协议号区间不能有交集
//                             assert(!(Math.max(protocolDef[0], def.def[0]) <= Math.min(protocolDef[1], def.def[1])),
//                                 errMsg(`协议号区间(${match[2]})与[${def.fileName}.kproto]的协议号区间(${def.def.join(",")})冲突`))
//                         })
//                         curProtocol = protocolDef[0];
//                         this.curProtocol = Math.max(this.curProtocol, protocolDef[1] + 1);
//                         this.protocolDefs.push({ fileName, def: protocolDef });
//                     }
//                 }
//             } else {
//                 let match = ln.match(/^\s*\/\/(.*)/);
//                 if (match) {
//                     //匹配到注释
//                     note.push(match[1]);
//                     return;
//                 }
//                 if (!comDef && !protoDef) {
//                     //===匹配定义
//                     match = ln.match(/^\s*(com|proto) +([_0-9a-zA-Z]+) *({|;)/)
//                     if (match) {
//                         //匹配到定义
//                         let name = match[2];
//                         if (match[1] == "com") {
//                             assert(match[3] != ";", errMsg(`通用结构定义不能为空`))
//                             //通用结构定义
//                             this.comDefs.push(def = comDef = {
//                                 fileName,
//                                 voName: `vo_${name}`,
//                                 note,
//                                 structName: name,
//                                 fields: [],
//                                 structs: [],
//                                 struct: "[]"
//                             })
//                         } else if (match[1] == "proto") {
//                             //协议结构定义
//                             this.protoDefs.push(protoDef = {
//                                 protocol: undefined,
//                                 protoName: name,
//                                 fileName,
//                                 note,
//                                 structs: []
//                             });
//                             if (curProtocol) {
//                                 protoDef.protocol = curProtocol++;
//                                 assert(protoDef.protocol <= protocolDef[1], errMsg(`协议号${protoDef.protocol}超出定义的结束协议号${protocolDef[1]}，请扩充`));
//                             }
//                             if (match[3] == ";") {
//                                 //无结构纯定义
//                                 protoDef = null;
//                             }
//                         }
//                     } else {
//                         checkOther(ln);
//                     }
//                 } else {
//                     //===读取定义

//                     /** 匹配字段 */
//                     function matchField(fields: IFieldDef[]) {
//                         match = ln.match(fieldReg);
//                         if (match) {
//                             //匹配到字段
//                             fields.push(parseField(match));
//                             return true;
//                         }
//                         return false;
//                     }

//                     /** 匹配结束 */
//                     function matchEnd() {
//                         if (ln.match(/^\s*\}/)) {
//                             return true;
//                         } else {
//                             checkOther(ln);
//                         }
//                         return false;
//                     }

//                     if (!structs) {

//                         /** 匹配内部结构 */
//                         function matchStruct(_structs: IStructDef[]) {
//                             match = ln.match(/^\s*struct *{/);
//                             if (match) {
//                                 structs = _structs;
//                                 return true;
//                             }
//                             return false;
//                         }

//                         if (comDef) {
//                             //===读取通用结构定义
//                             if (!matchField(comDef.fields)) {
//                                 if (!matchStruct(comDef.structs)) {
//                                     if (matchEnd()) {
//                                         comDef.struct = buildFieldsStruct(comDef.fields);
//                                         assert(comDef.struct, "通用结构定义不能为空");
//                                         def = comDef = null;
//                                     }
//                                 }
//                             }
//                         } else if (protoDef) {
//                             //===读取协议结构定义
//                             if (!def) {
//                                 //匹配tos/toc结构
//                                 match = ln.match(/^\s*(tos|toc) *{/);
//                                 if (match) {
//                                     let structName = `${match[1]}_${protoDef.protoName}`;
//                                     def = {
//                                         note,
//                                         structName: structName,
//                                         voName: `vo_${structName}`,
//                                         fields: [],
//                                         struct: ""
//                                     }
//                                     if (match[1] == "tos") {
//                                         protoDef.tosStruct = def;
//                                     } else {
//                                         protoDef.tocStruct = def;
//                                     }
//                                 } else if (!matchStruct(protoDef.structs)) {
//                                     if (matchEnd()) {
//                                         protoDef = null;
//                                     }
//                                 }
//                             } else {
//                                 //===读取tos/toc结构定义
//                                 if (!matchField(def.fields)) {
//                                     if (matchEnd()) {
//                                         def.struct = buildFieldsStruct(def.fields);
//                                         if (!def.struct) {
//                                             //没有结构
//                                             def.voName = "undefined";
//                                         }
//                                         def = null;
//                                     }
//                                 }
//                             }
//                         }

//                     } else {
//                         //===读取内部结构定义
//                         if (!struct) {
//                             match = ln.match(/^\s*([_0-9a-zA-Z]+) *{/);
//                             if (match) {
//                                 //匹配到内部结构
//                                 let name = `${comDef ? comDef.structName : protoDef.protoName}_${match[1]}`;
//                                 let voName = `vo_${name}`;
//                                 structs.push(struct = {
//                                     note,
//                                     structName: name,
//                                     voName,
//                                     fields: [],
//                                     struct: ""
//                                 })
//                             } else if (matchEnd()) {
//                                 structs = null;
//                             }
//                         } else {
//                             //===读取内部结构定义
//                             if (!matchField(struct.fields)) {
//                                 if (matchEnd()) {
//                                     struct.struct = buildFieldsStruct(struct.fields);
//                                     assert(struct.struct, "内部结构定义不能为空");
//                                     struct = null;
//                                 }
//                             }
//                         }
//                     }
//                 }
//                 note = [];
//             }

//             function errMsg(msg: string) {
//                 return `[${fileName}.kproto]:${lnIdx + 1} >>> ${ln} >>> ${msg}`
//             }

//             function checkOther(ln: string) {
//                 assert(!/\S/.test(ln), errMsg("错误定义"))
//             }

//             /** 解析字段 */
//             function parseField(match: RegExpMatchArray): IFieldDef {
//                 let name = match[1];
//                 /** 是否使用通用结构 */
//                 let isCom = match[2] == "@";
//                 let type = match[3];
//                 /** 特殊浮点型参数 */
//                 let floatParam = match[4] ? parseInt(match[4]) : 0;
//                 /** 数组维度 */
//                 let arrVec = match[5] === "" ? 1 : match[5] ? parseInt(match[5]) : 0;

//                 let stfn = "";
//                 let tsType: string;
//                 let struct: any[] = [`"${name.replace("?", "")}"`];
//                 switch (type) {
//                     case "bool":
//                         tsType = "boolean"
//                         struct.push(arrVec ? VT.boolArr : VT.bool)
//                         break
//                     case "uint":
//                         tsType = "number"
//                         struct.push(arrVec ? VT.uintArr : VT.uint)
//                         break
//                     case "int":
//                         tsType = "number"
//                         struct.push(arrVec ? VT.intArr : VT.int)
//                         break
//                     case "float":
//                         tsType = "number"
//                         struct.push(arrVec ? VT.floatArr : VT.float)
//                         break
//                     case "floatUint":
//                         tsType = "number"
//                         struct.push(arrVec ? VT.floatUintArr : VT.floatUint)
//                         break
//                     case "floatInt":
//                         tsType = "number"
//                         struct.push(arrVec ? VT.floatIntArr : VT.floatInt)
//                         break
//                     case "floatStr":
//                         tsType = "number"
//                         struct.push(arrVec ? VT.floatStrArr : VT.floatStr)
//                         break
//                     case "str":
//                         tsType = "string"
//                         struct.push(arrVec ? VT.strArr : VT.str)
//                         break
//                     case "obj":
//                         tsType = "any"
//                         struct.push(VT.obj)
//                         break
//                     case "arr":
//                         tsType = "any[]"
//                         struct.push(VT.arr)
//                         break
//                     default:
//                         //自定义结构类型
//                         if (isCom) {
//                             //通用结构
//                             tsType = `vo_${type}`
//                             stfn = `ST.${type}()`
//                         } else {
//                             //内部结构
//                             tsType = `vo_${comDef ? def.structName : protoDef.protoName}_${type}`
//                             stfn = `ST.${comDef ? def.structName : protoDef.protoName}_${type}()`
//                         }
//                         struct.push(arrVec ? VT.structArr : VT.struct);
//                         break
//                 }
//                 if (arrVec) {
//                     //数组处理
//                     struct.push(arrVec);
//                     while (arrVec-- > 0) {
//                         tsType += "[]"
//                     }
//                 }
//                 //特殊参数处理
//                 floatParam && struct.push(floatParam);
//                 stfn && struct.push(stfn);

//                 return {
//                     lnIdx,
//                     note,
//                     name,
//                     type: tsType,
//                     struct: `[${struct.join(", ")}]`
//                 }
//             }
//         });
//         assert(protocolDef, `[${fileName}.kproto] >>> 未找到protocol定义`);

//         /** 构建字段结构 */
//         function buildFieldsStruct(fields: IFieldDef[]) {
//             if (fields.length) {
//                 let structs = [];
//                 fields.forEach(field => structs.push(field.struct));
//                 return `[${structs.join(", ")}]`;
//             } else {
//                 return "";
//             }
//         }
//     }

//     /** 根据协议号排序 */
//     private sortProto() {
//         //先给没有协议号的在当前最大协议号后递增附一个
//         this.protoDefs.forEach(def => {
//             if (!def.protocol) {
//                 def.protocol = this.curProtocol++;
//             }
//         })
//         this.protoDefs.sort((a, b) => a.protocol - b.protocol);
//     }

//     /** 构建协议代码 */
//     private buildCodeStr() {
//         let code = "//工具生成，请不要手动修改...\n";

//         //写入kcoder初始化
//         code += "let ObjEncoder: any, ObjDecoder: any\n";
//         code += "/** 需要传入kcoder模块来进行初始化 */\n";
//         code += `export function init${this.clsName}(kcoder: { ObjEncoder: any, ObjDecoder: any }) {\n`;
//         code += "    ObjEncoder = kcoder.ObjEncoder\n";
//         code += "    ObjDecoder = kcoder.ObjDecoder\n";
//         code += "}\n\n";

//         //写入协议号
//         code += "/** 协议 */\n";
//         code += `export const enum ${this.clsName} {\n`;
//         this.protoDefs.forEach(proto => {
//             buildNote(proto.note, "    ");
//             code += `    ${proto.protoName} = ${proto.protocol},\n`;
//         })
//         code += "}\n\n";

//         //写入通用结构和内部结构
//         code += "const ST = {\n";
//         let structs: IStructDef[] = [...this.comDefs];
//         this.comDefs.forEach(com => structs = structs.concat(com.structs));
//         this.protoDefs.forEach(proto => structs = structs.concat(proto.structs));
//         structs.forEach(struct => {
//             code += `    ${struct.structName}: () => ${struct.struct},\n`;
//         })
//         code += "}\n\n";

//         //写入协议tos结构
//         code += "const STRUCT_TOS: any = {\n";
//         this.protoDefs.forEach(proto => {
//             if (proto.tosStruct) {
//                 code += `    ${proto.protocol}: ${proto.tosStruct.struct},\n`;
//             }
//         })
//         code += "}\n\n";

//         //写入协议toc结构
//         code += "const STRUCT_TOC: any = {\n";
//         this.protoDefs.forEach(proto => {
//             if (proto.tocStruct) {
//                 code += `    ${proto.protocol}: ${proto.tocStruct.struct},\n`;
//             }
//         })
//         code += "}\n\n";

//         //写入协议定义
//         code += "/** 协议Vo定义 */\n";
//         code += "export namespace ProtoVo {\n\n";

//         //写入tos def
//         code += "    /** 协议请求结构定义 */\n";
//         code += "    export type TosDef = {\n";
//         this.protoDefs.forEach(proto => {
//             if (proto.tosStruct) {
//                 code += `        [${this.clsName}.${proto.protoName}]: ${proto.tosStruct.voName}\n`;
//             }
//         });
//         code += "    }\n\n";

//         //写入toc def
//         code += "    /** 协议返回结构定义 */\n";
//         code += "    export type TocDef = {\n";
//         this.protoDefs.forEach(proto => {
//             if (proto.tocStruct) {
//                 code += `        [${this.clsName}.${proto.protoName}]: ${proto.tocStruct.voName}\n`;
//             }
//         });
//         code += "    }\n\n";

//         //写入读写方法
//         code += "    /** 二进制数据转换为协议vo(发服务端) */\n";
//         code += "    export function fromBytesTos(bytes: Uint8Array) {\n";
//         code += "        let protocol: number, data = ObjDecoder.decodeDeal(bytes, (r: any) => { protocol = r.uint; return STRUCT_TOS[protocol] })\n";
//         code += "        return { protocol, data }\n";
//         code += "    }\n\n";
//         code += "    /** 协议vo转换为二进制数据(发服务端) */\n";
//         code += "    export function toBytesTos<P extends keyof TosDef>(protocol: P, data: TosDef[P]) {\n";
//         code += "        return ObjEncoder.encodeDeal(data, STRUCT_TOS[protocol], (w: any) => w.uint = protocol)\n";
//         code += "    }\n\n"
//         code += "    /** 二进制数据转换为协议vo(发客户端) */\n";
//         code += "    export function fromBytesToc(bytes: Uint8Array) {\n";
//         code += "        let protocol: number, data = ObjDecoder.decodeDeal(bytes, (r: any) => { protocol = r.uint; return STRUCT_TOC[protocol] })\n";
//         code += "        return { protocol, data }\n";
//         code += "    }\n\n";
//         code += "    /** 协议vo转换为二进制数据(发客户端) */\n";
//         code += "    export function toBytesToc<P extends keyof TocDef>(protocol: P, data: TocDef[P]) {\n";
//         code += "        return ObjEncoder.encodeDeal(data, STRUCT_TOC[protocol], (w: any) => w.uint = protocol)\n";
//         code += "    }\n\n"

//         //写入vo
//         let defs: IStructDef[] = [];
//         this.comDefs.forEach(def => {
//             defs.push(def, ...def.structs);
//         })
//         this.protoDefs.forEach(def => {
//             defs.push(...def.structs);
//             def.tosStruct && defs.push(def.tosStruct);
//             def.tocStruct && defs.push(def.tocStruct);
//         })
//         defs.forEach(def => {
//             buildNote(def.note, "    ");
//             code += `    export interface ${def.voName} {\n`;
//             def.fields.forEach(field => {
//                 buildNote(field.note, "        ");
//                 code += `        ${field.name}: ${field.type}\n`;
//             });
//             code += "    }\n\n";
//         })

//         code += "}"

//         //构建完成
//         this.codeStr = code;

//         /** 构建注释 tab：缩进*/
//         function buildNote(note: string[], tab: string) {
//             if (!note || !note.length) return;
//             if (note.length == 1) {
//                 //单行注释
//                 code += `${tab}/** ${note} */\n`;
//             } else {
//                 //多行注释
//                 code += `${tab}/**\n`;
//                 note.forEach(line => code += `${tab} * ${line}\n`);
//                 code += `${tab} */\n`;
//             }
//         }
//     }
// }

// /** 字段正则 */
// const fieldReg = /^\s*([_0-9a-zA-Z]+\??) *: *(?:(@?)([_0-9a-zA-Z]+)(?:\((\d+)\))*(?:\[(\d*)\])*)+ *;?/;

// /** 断言失败退出程序并输出错误信息 */
// function assert(cond: any, msg?: string) {
//     if (!cond) {
//         console.log(msg);
//         process.exit();
//     }
//     return cond;
// }

// /** 字段定义 */
// interface IFieldDef {
//     lnIdx: number, note: string[], name: string, type: string, struct: string
// }

// /** 结构定义 */
// interface IStructDef {
//     note: string[], structName: string, voName: string, fields: IFieldDef[], struct: string
// }

// /** 通用结构定义 */
// interface ICommonDef extends IStructDef {
//     fileName: string, structs: IStructDef[]
// }

// /** 协议定义 */
// interface IProtoDef {
//     /** 注释 */
//     note: string[],
//     /** 协议号 */
//     protocol: number,
//     /** 协议名 */
//     protoName: string,
//     /** 文件名 */
//     fileName: string,
//     /** 发服务端结构 */
//     tosStruct?: IStructDef,
//     /** 发客户端结构 */
//     tocStruct?: IStructDef
//     /** 内部结构 */
//     structs?: IStructDef[]
// }